home *** CD-ROM | disk | FTP | other *** search
/ NeXTSTEP 3.3 (Developer)…68k, x86, SPARC, PA-RISC] / NeXTSTEP 3.3 Dev Intel.iso / NextDeveloper / Examples / DriverKit / AMDPCSCSIDriver / AMDPCSCSIDriver_reloc.tproj / AMD_Chip.m < prev    next >
Encoding:
Text File  |  1995-02-10  |  15.4 KB  |  654 lines

  1. /*     Copyright (c) 1994 NeXT Computer, Inc.  All rights reserved. 
  2.  *
  3.  * AMD_Chip.m - chip (53C974/79C974) specific methods for AMD SCSI driver
  4.  *
  5.  * HISTORY
  6.  * 21 Oct 94    Doug Mitchell at NeXT
  7.  *      Created. 
  8.  */
  9.  
  10. #import "AMD_Chip.h"
  11. #import "AMD_ChipPrivate.h"
  12. #import "AMD_Private.h"
  13. #import "AMD_x86.h"
  14. #import "AMD_Regs.h"
  15. #import "AMD_Types.h"
  16. #import "AMD_ddm.h"
  17. #import "bringup.h"
  18. #import <driverkit/generalFuncs.h>
  19. #import <kernserv/prototypes.h>
  20.  
  21. IONamedValue scsiMsgValues[] = {
  22.     {MSG_CMDCMPLT,        "Command Complete"    },
  23.     {MSG_EXTENDED,        "Extended Message"    },
  24.     {MSG_SAVEPTRS,        "Save Pointers"        },
  25.     {MSG_RESTOREPTRS,    "Restore Pointers"    },
  26.     {MSG_DISCONNECT,    "Disconnect"        },
  27.     {MSG_IDETERR,        "Initiator Det Error"    },
  28.     {MSG_ABORT,        "Abort"            },
  29.     {MSG_MSGREJECT,        "Message Reject"    },
  30.     {MSG_NOP,        "Nop"            },
  31.     {MSG_MSGPARERR,        "Message parity Error"    },
  32.     {0,            NULL            }
  33. };
  34.  
  35. #ifdef    DDM_DEBUG
  36. IONamedValue scsiPhaseValues[] = {
  37.     {PHASE_DATAOUT,        "data_out"        },
  38.     {PHASE_DATAIN,        "data_in"        },
  39.     {PHASE_COMMAND,        "command"        },
  40.     {PHASE_STATUS,        "status"        },
  41.     {PHASE_MSGOUT,        "message_out"        },
  42.     {PHASE_MSGIN,        "message_in"        },
  43.     {0,            NULL            }
  44. };
  45.  
  46. #endif    DDM_DEBUG
  47.  
  48. #ifdef    DEBUG
  49. /*
  50.  * For IOFindNameForValue() and ddm's.
  51.  */
  52. IONamedValue scStateValues[] = { 
  53.     {SCS_UNINITIALIZED,    "SCS_UNINITIALIZED"    },
  54.         {SCS_DISCONNECTED,    "SCS_DISCONNECTED"    },
  55.         {SCS_SELECTING,        "SCS_SELECTING"        },
  56.         {SCS_INITIATOR,        "SCS_INITIATOR"     },
  57.         {SCS_COMPLETING,    "SCS_COMPLETING"    },
  58.         {SCS_DMAING,        "SCS_DMAING"        },    
  59.         {SCS_ACCEPTINGMSG,    "SCS_ACCEPTINGMSG"    },
  60.         {SCS_SENDINGMSG,    "SCS_SENDINGMSG"    },    
  61.         {SCS_GETTINGMSG,    "SCS_GETTINGMSG"    },    
  62.     {SCS_SENDINGCMD,    "SCS_SENDINGCMD"    },
  63.     {0,             NULL            },
  64. };
  65. #endif    DEBUG
  66.  
  67. @implementation AMD_SCSI(Chip)
  68.  
  69. /*
  70.  * One-time-only init and probe. Returns YES if a functioning chip is 
  71.  * found, else returns NO. -hwReset must be called subsequent to this 
  72.  * to enable operation of the chip.
  73.  */
  74. - (BOOL)probeChip
  75. {
  76.     int target;
  77.     
  78.     /*
  79.      * Init sync mode to async, until we negotiate.
  80.      */
  81.     for(target=0; target<SCSI_NTARGETS; target++) {
  82.         perTarget[target].syncXferOffset = 0;
  83.     }
  84.     return YES;
  85. }
  86.  
  87. /*
  88.  * Reusable 53C974 init function. This includes a SCSI reset.
  89.  * Handling of ioComplete of active and disconnected commands must be done
  90.  * elsewhere. Returns non-zero on error. 
  91.  */
  92. - (int)hwReset : (const char *)reason
  93. {
  94.     int         target;
  95.     unsigned char     reg;
  96.     
  97.     /*
  98.      * First of all, reset interrupts, the SCSI block, and the DMA engine.
  99.      */
  100.     [self disableAllInterrupts];
  101.     WRITE_REG(scsiCmd, SCMD_RESET_DEVICE);
  102.     WRITE_REG(scsiCmd, SCMD_NOP);
  103.     [self dmaIdle];
  104.     
  105.     /*
  106.      * Clear possible pending interrupt.
  107.      */
  108.     READ_REG(intrStatus);
  109.     
  110.     /*
  111.      * Init state variables.
  112.      */
  113.     reselPending  = 0;
  114.     scState       = SCS_DISCONNECTED;
  115.     activeCmd     = NULL;
  116.     currMsgInCnt  = 0;
  117.     currMsgOutCnt = 0;
  118.     msgOutState   = MOS_NONE;
  119.     SDTR_State    = SNS_NONE;
  120.     
  121.     /*
  122.      * Sync negotiation is needed after a reset.
  123.      */
  124.     for(target=0; target<SCSI_NTARGETS; target++) {
  125.         perTarget[target].syncNegotNeeded = 1;
  126.     }
  127.     
  128.     /*
  129.      * Control1....
  130.      */
  131.     reg = CR1_RESET_INTR_DIS | CR1_PERR_ENABLE | AMD_SCSI_ID;
  132.     if(extendTiming) {
  133.         /*
  134.          * Per instance table. This slows down transfers on the
  135.          * bus.
  136.          */
  137.         reg |= CR1_EXTEND_TIMING;
  138.     }
  139.     WRITE_REG(control1, reg);
  140.     ddm_init("control1 = 0x%x\n", reg, 2,3,4,5);
  141.     hostId = AMD_SCSI_ID;
  142.     
  143.     /*
  144.      * Clock factor and select timeout.
  145.      */
  146.     ASSERT(scsiClockRate != 0);
  147.     if(scsiClockRate < 10) {
  148.         IOLog("AMD53C974: Clock %d MHZ too low; using 10 MHz\n",
  149.              scsiClockRate);
  150.         scsiClockRate = 10;
  151.     }
  152.     if(scsiClockRate > 40) {
  153.         IOLog("AMD53C974: Clock %d MHZ too high; using 40 MHz\n",
  154.              scsiClockRate);
  155.         scsiClockRate = 40;
  156.     }
  157.     reg = AMD_CLOCK_FACTOR(scsiClockRate) & 0x7;
  158.     WRITE_REG(clockFactor, reg);
  159.     ddm_init("clockFactor %d\n", reg, 2,3,4,5);
  160.     reg = amdSelectTimeout(AMD_SELECT_TO, scsiClockRate);
  161.     WRITE_REG(scsiTimeout, reg);
  162.     ddm_init("select timeout reg 0x%x\n", reg, 2,3,4,5);
  163.     
  164.     /*
  165.      * control2 - enable extended features - mainly, 24-bit transfer count.
  166.      */
  167.     WRITE_REG(control2, CR2_ENABLE_FEAT);
  168.     
  169.     /*
  170.      * control3
  171.      */
  172.     reg = 0;
  173.     if(fastModeEnable) {
  174.         reg |= CR3_FAST_SCSI;
  175.     }
  176.     if(scsiClockRate > 25) {
  177.         reg |= CR3_FAST_CLOCK;
  178.     }
  179.     ddm_init("control3 = 0x%x\n", reg, 2,3,4,5);
  180.     WRITE_REG(control3, reg);
  181.     
  182.     /*
  183.      * control4 - glitch eater, active negation. Let's not 
  184.      * worry about these whizzy features just yet.
  185.      */
  186.     WRITE_REG(control4, 0);
  187.     
  188.     /*
  189.      * Go to async xfer mode for now. Sync gets enabled on a per-target 
  190.      * basis in -targetContext.
  191.      */
  192.     WRITE_REG(syncOffset, 0);
  193.     
  194.     /*
  195.      * Reset SCSI bus, wait, clear possible interrupt.
  196.      */
  197.     WRITE_REG(scsiCmd, SCMD_RESET_SCSI);
  198.     if(reason) {
  199.         IOLog("AMD53C974: Resetting SCSI bus (%s)\n", reason);
  200.     }
  201.     else {
  202.         IOLog("AMD53C974: Resetting SCSI bus\n");
  203.     }
  204.     IOSleep(AMD_SCSI_RESET_DELAY);
  205.     READ_REG(intrStatus);
  206.  
  207.     ddm_init("hwReset: enabling interrupts\n", 1,2,3,4,5);
  208.     [self enableAllInterrupts];
  209.     
  210.     ddm_init("hwReset: DONE\n", 1,2,3,4,5);
  211.     return 0;    
  212. }
  213.  
  214. /*
  215.  * reset SCSI bus.
  216.  */
  217. - (void)scsiReset
  218. {
  219.     WRITE_REG(scsiCmd, SCMD_RESET_SCSI);
  220.     READ_REG(intrStatus);
  221. }
  222.  
  223. /*
  224.  * Start a SCSI transaction for the specified command. ActiveCmd must be 
  225.  * NULL. A return of HWS_REJECT indicates that caller may try again
  226.  * with another command; HWS_BUSY indicates a condition other than
  227.  * (activeCmd != NULL) which prevents the processing of the command.
  228.  */
  229. - (hwStartReturn)hwStart : (commandBuf *)cmdBuf
  230. {    
  231.     unsigned char    cdb_ctrl;
  232.     IOSCSIRequest    *scsiReq = cmdBuf->scsiReq;
  233.     cdb_t        *cdbp = &scsiReq->cdb;
  234.     unsigned char    identify_msg = 0;
  235.     unsigned char    *cp;
  236.     unsigned char    okToDisc;
  237.     unsigned char    okToQueue;
  238.     perTargetData    *perTargetPtr;
  239.     int        i;
  240.     BOOL        cmdQueueDisableFlag = NO;
  241.     unsigned char    selectCmd;
  242.     
  243.     ddm_chip("hwStart cmdBuf = 0x%x opcode %s\n", cmdBuf, 
  244.         IOFindNameForValue(cdbp->cdb_opcode, IOSCSIOpcodeStrings),
  245.             3,4,5);
  246.     ASSERT(activeCmd == NULL);
  247.     
  248.     /*
  249.      * Currently, the only reason we return HWS_BUSY is if we have
  250.      * a reselect pending.
  251.      */
  252.     if(reselPending) {
  253.         queue_enter(&pendingQ, cmdBuf, commandBuf *, link);
  254.         return HWS_BUSY;
  255.     }
  256.     ASSERT(scState == SCS_DISCONNECTED);
  257.         
  258.     /*
  259.      * Initialize driver return values and state machine.
  260.      */
  261.     cmdBuf->currentByteCount = cmdBuf->savedByteCount = 
  262.         scsiReq->maxTransfer;
  263.     scsiReq->bytesTransferred = 0;
  264.     cmdBuf->savedPtr = cmdBuf->currentPtr = (vm_offset_t)cmdBuf->buffer;
  265.     scsiReq->driverStatus = SR_IOST_INVALID;
  266.     scsiReq->totalTime  = 0ULL;
  267.     scsiReq->latentTime = 0ULL;
  268.     
  269.     /*
  270.      * Figure out what kind of cdb we've been given and grab the ctrl byte.
  271.      */
  272.     switch (SCSI_OPGROUP(cdbp->cdb_opcode)) {
  273.         case OPGROUP_0:
  274.         cmdBuf->cdbLength = sizeof(cdb_6_t);
  275.         cdb_ctrl  = cdbp->cdb_c6.c6_ctrl;
  276.         break;
  277.         case OPGROUP_1:
  278.         case OPGROUP_2:
  279.         cmdBuf->cdbLength = sizeof(cdb_10_t);
  280.         cdb_ctrl  = cdbp->cdb_c10.c10_ctrl;
  281.         break;
  282.         case OPGROUP_5:
  283.         cmdBuf->cdbLength = sizeof(cdb_12_t);
  284.         cdb_ctrl  = cdbp->cdb_c12.c12_ctrl;
  285.         break;
  286.             case OPGROUP_6:
  287.         cmdBuf->cdbLength = (scsiReq->cdbLength ? 
  288.              scsiReq->cdbLength : sizeof (struct cdb_6));
  289.         cdb_ctrl = 0;
  290.         break;
  291.         case OPGROUP_7:
  292.         cmdBuf->cdbLength = (scsiReq->cdbLength ? 
  293.              scsiReq->cdbLength : sizeof (struct cdb_10));
  294.         cdb_ctrl = 0;
  295.         break;
  296.         default:
  297.         goto abortReq;
  298.     }
  299.     ddm_chip("cdbLength = %d\n", cmdBuf->cdbLength, 2,3,4,5);
  300.     
  301.     /*
  302.      * Do a little command snooping.
  303.      */
  304.     perTargetPtr = &perTarget[scsiReq->target];
  305.     switch(cdbp->cdb_opcode) {
  306.         case C6OP_INQUIRY:
  307.         /*
  308.          * The first command SCSIDisk sends us is an Inquiry command.
  309.          * This never gets retried, so avoid a possible 
  310.          * reject of a command queue tag. Avoid this hack if
  311.          * there are any other commands outstanding for this
  312.          * target/lun.
  313.          */
  314.         if(activeArray[scsiReq->target][scsiReq->lun] == 0) {
  315.             cmdQueueDisableFlag = YES;
  316.         }
  317.         break;
  318.         
  319.         case C6OP_REQSENSE:
  320.             /*
  321.          * Always force sync renegotiation on this one to 
  322.          * catch independent target power cycles.
  323.          */
  324.         if(SYNC_RENEGOT_ON_REQ_SENSE) {
  325.             perTargetPtr->syncNegotNeeded = 1;
  326.         }
  327.         break;
  328.     }
  329.         
  330.     /*
  331.      * Avoid command queueing if if we're going to do sync
  332.      * negotiation.
  333.      * FIXME - this might be illegal - what if we're doing a request 
  334.      * sense in response to a legitimate error, and there are 
  335.      * tagged commands pending?
  336.      */
  337.     if(perTargetPtr->syncNegotNeeded &&
  338.        !perTargetPtr->syncDisable &&
  339.        syncModeEnable) {
  340.            cmdQueueDisableFlag = YES;
  341.         SDTR_State = SNS_HOST_INIT_NEEDED;
  342.         ddm_chip("hwStart: entering SNS_HOST_INIT_NEEDED state\n", 
  343.             1,2,3,4,5);
  344.     }
  345.     else {
  346.         SDTR_State = SNS_NONE;
  347.     }
  348.     
  349.     /*
  350.      * Determine from myriad sources whether or not it's OK to 
  351.      * disconnect and to use command queueing. 
  352.      */
  353.     okToQueue = cmdQueueEnable &&            // global per driver
  354.                 !scsiReq->cmdQueueDisable &&     // per I/O
  355.                 !perTargetPtr->cmdQueueDisable &&      // per target
  356.             !cmdQueueDisableFlag;        // inquiry hack
  357.     okToDisc  = ([self numReserved] >         // > 1 target on bus
  358.             (1 + SCSI_NLUNS)) || 
  359.             okToQueue;                // hope to do cmd q'ing
  360.     #if    FORCE_DISCONNECTS
  361.     okToDisc = 1;
  362.     #else    FORCE_DISCONNECTS
  363.     if(!scsiReq->disconnect) {
  364.         /*
  365.          * This overrides everything...
  366.          */
  367.         okToQueue = okToDisc = 0;
  368.     }
  369.     #endif    FORCE_DISCONNECTS
  370.     cmdBuf->discEnable = okToDisc;
  371.     if(okToQueue) {
  372.         /*
  373.          * Avoid using tag QUEUE_TAG_NONTAGGED...
  374.          */
  375.         cmdBuf->queueTag = nextQueueTag;
  376.         if(++nextQueueTag == QUEUE_TAG_NONTAGGED) {
  377.             nextQueueTag++;
  378.         }
  379.     }
  380.     else {
  381.         cmdBuf->queueTag = QUEUE_TAG_NONTAGGED;
  382.     }
  383.     
  384.     /*
  385.      * Make sure nothing unreasonable has been asked of us. 
  386.      */
  387.     if((cdb_ctrl & CTRL_LINKFLAG) != CTRL_NOLINK) {
  388.         ddm_err("Linked CDB (Unimplemented)\n",
  389.             1,2,3,4,5);
  390.         goto abortReq;
  391.     }
  392.  
  393.     /*
  394.      * OK, this command is hot.
  395.      */
  396.     [self activateCommand:cmdBuf];
  397.     
  398.     scState = SCS_SELECTING;
  399.     msgOutState = MOS_NONE;
  400.     bzero(currMsgIn, AMD_MSG_SIZE);
  401.     bzero(currMsgOut, AMD_MSG_SIZE);
  402.     currMsgInCnt = 0;
  403.     currMsgOutCnt = 0;
  404.     
  405.     /*
  406.      * Load per-target context.
  407.      */
  408.     [self targetContext:scsiReq->target];
  409.  
  410.     /*
  411.      * set target bus id
  412.      * punch message(s), optional cdb into fifo
  413.      * write appropriate select command
  414.      */
  415.     ddm_chip("hwStart: opcode 0x%x targ %d lun %d maxTransfer 0x%x\n", 
  416.          cdbp->cdb_opcode, scsiReq->target, scsiReq->lun, 
  417.          scsiReq->maxTransfer, 5);
  418.     WRITE_REG(scsiCmd, SCMD_CLEAR_FIFO);
  419.     WRITE_REG(scsiDestID, scsiReq->target);
  420.     identify_msg = MSG_IDENTIFYMASK | (scsiReq->lun & MSG_ID_LUNMASK);
  421.     if(okToDisc) {
  422.         identify_msg |= MSG_ID_DISCONN;
  423.     }
  424.  
  425.     WRITE_REG(scsiFifo, identify_msg);
  426.     
  427.     /*
  428.      * Note this logic assumes that queue tag and SDTR messages are
  429.      * mutually exclusive...
  430.      */
  431.     if(SDTR_State == SNS_HOST_INIT_NEEDED) {
  432.         selectCmd = SCMD_SELECT_ATN_STOP;
  433.     }
  434.     else {
  435.         if(okToQueue) {
  436.             WRITE_REG(scsiFifo, MSG_SIMPLE_QUEUE_TAG);
  437.             WRITE_REG(scsiFifo, cmdBuf->queueTag);
  438.             
  439.             /*
  440.              * Save these in currMsgOut[] in case 
  441.              * the target rejects this message.
  442.              */
  443.             currMsgOut[0] = MSG_SIMPLE_QUEUE_TAG;
  444.             currMsgOut[1] = cmdBuf->queueTag;
  445.             currMsgOutCnt = 2;
  446.         }
  447.         cp = (u_char *)cdbp;
  448.         for(i=0; i<cmdBuf->cdbLength; i++) {
  449.             WRITE_REG(scsiFifo, *cp++);
  450.         }
  451.         if(okToQueue) {
  452.             selectCmd = SCMD_SELECT_ATN_3;
  453.         }
  454.         else {
  455.             selectCmd = SCMD_SELECT_ATN;
  456.         }
  457.     }
  458.     WRITE_REG(scsiCmd, selectCmd);
  459.     IOGetTimestamp(&cmdBuf->startTime);
  460.     return HWS_OK;
  461.     
  462. abortReq:
  463.     scsiReq->driverStatus = SR_IOST_CMDREJ;
  464.     [self ioComplete:cmdBuf];
  465.     return HWS_REJECT;
  466. }
  467.  
  468. /*
  469.  * SCSI device interrupt handler.
  470.  */
  471. - (void)hwInterrupt
  472. {
  473.     ddm_chip("hwInterrupt: activeCmd 0x%x\n", activeCmd, 2,3,4,5);
  474.     
  475.     switch([self scsiInterruptPending]) {
  476.         case SINT_NONE:
  477.         /*
  478.          * Must be another device....
  479.          */
  480.         [self enableAllInterrupts];
  481.         return;
  482.         case SINT_DEVICE:
  483.         case SINT_DMA:
  484.             break;
  485.         default:
  486.             /* 
  487.          * What do we do now, batman?
  488.          */
  489.         [self hwAbort:SR_IOST_HW reason:"Bad Interrupt Received"];
  490.         return;
  491.     }
  492.     
  493. goAgain:
  494.     /*
  495.      * Save interrupt state.
  496.      */
  497.     saveStatus     = READ_REG(scsiStat);
  498.     saveSeqStep    = READ_REG(internState);
  499.     saveIntrStatus = READ_REG(intrStatus);
  500.         
  501.     ddm_chip("   status 0x%x intstatus 0x%x scState %s\n", 
  502.         saveStatus, saveIntrStatus, 
  503.         IOFindNameForValue(scState, scStateValues), 4,5);
  504.     if((saveStatus & SS_ILLEGALOP) || (saveIntrStatus & IS_ILLEGALCMD)) {
  505.        
  506.          /*
  507.          * Software screwup. Start over from scratch.
  508.          */
  509.         IOLog("AMD53C974: hardware command reject\n");
  510.         [self hwAbort:SR_IOST_INT reason:"Hardware Command Reject"];
  511.         return;
  512.     }
  513.  
  514.     /*
  515.      * OK, grind thru the state machine.
  516.      */
  517.     switch(scState) {
  518.            case SCS_DISCONNECTED:
  519.            [self fsmDisconnected];
  520.         break;
  521.            case SCS_SELECTING:
  522.            [self fsmSelecting];
  523.         break;
  524.            case SCS_INITIATOR:
  525.            [self fsmInitiator];
  526.         break;
  527.            case SCS_COMPLETING:
  528.            [self fsmCompleting];
  529.         break;
  530.            case SCS_DMAING:
  531.            [self fsmDMAing];
  532.         break;
  533.            case SCS_ACCEPTINGMSG:
  534.            [self fsmAcceptingMsg];
  535.         break;
  536.            case SCS_SENDINGMSG:
  537.            [self fsmSendingMsg];
  538.         break;
  539.            case SCS_GETTINGMSG:
  540.            [self fsmGettingMsg];
  541.         break;
  542.        case SCS_SENDINGCMD:
  543.            [self fsmSendingCmd];
  544.         break;
  545.        default:
  546.            IOPanic("AMD53C974: Bad scState");
  547.     } /* switch scState */
  548.     
  549.     if ((scState != SCS_DISCONNECTED) &&
  550.         (saveIntrStatus & IS_DISCONNECT)) {
  551.         /*
  552.          * the target just up and went away. This is a catch-all
  553.          * trap for any unexpected disconnect.
  554.          */
  555.         ddm_err("hwInterrupt: target disconnected\n", 1,2,3,4,5);
  556.         scState = SCS_DISCONNECTED;
  557.         if(activeCmd != NULL) {
  558.             activeCmd->scsiReq->driverStatus = SR_IOST_TABT;
  559.             [self ioComplete:activeCmd];
  560.             activeCmd = NULL;
  561.         }
  562.     }
  563.     
  564.     /*
  565.      * Handle a SCSI Phase change if necessary.
  566.      */
  567.     if (scState == SCS_INITIATOR)
  568.         [self fsmPhaseChange];
  569. #ifdef    DEBUG
  570.     else {
  571.         ddm_chip("hwInterrupt #2: scState %s\n", 
  572.             IOFindNameForValue(scState, scStateValues),
  573.             2,3,4,5);
  574.     }
  575. #endif    DEBUG
  576.  
  577.     /*
  578.      * If we're off the bus, enable reselection at chip level.
  579.      */
  580.     if (scState == SCS_DISCONNECTED) {
  581.         ddm_chip("hwInterrupt: enabling reselection\n", 1,2,3,4,5);
  582.         WRITE_REG(scsiCmd, SCMD_ENABLE_SELECT);
  583.     }
  584.     
  585.     
  586.     /*
  587.      * If another SCSI interrupt is pending, go for it again (avoiding 
  588.      * an unnecessary enableInterrupt and msg_receive()).
  589.      */
  590.     switch([self scsiInterruptPending]) {
  591.         case SINT_DEVICE:
  592.             #if    INTR_LATENCY_TEST
  593.         ddm_chip("hwInterrupt: INTR TRUE; EXITING FOR MEASUREMENT\n",
  594.             1,2,3,4,5);
  595.         break;
  596.         #else    INTR_LATENCY_TEST
  597.             ddm_chip("hwInterrupt: going again without enabling "
  598.             "interrupt\n", 1,2,3,4,5);
  599.             goto goAgain;
  600.         #endif    INTR_LATENCY_TEST
  601.         default:
  602.             break;
  603.     }
  604.  
  605.     [self enableAllInterrupts];
  606.     
  607.     /*
  608.      * One more thing - if we're still disconnected, enable processing
  609.      * of new commands. 
  610.      */
  611.     if(scState == SCS_DISCONNECTED)
  612.         [self busFree];
  613.     ddm_chip("hwInterrupt: DONE; scState %s\n", 
  614.         IOFindNameForValue(scState, scStateValues), 2,3,4,5);
  615. }
  616.  
  617.  
  618. - (void)logRegs
  619. {
  620. #if    DEBUG
  621.     unsigned char     cs, cis;
  622.     unsigned char     fifoDepth;
  623.     unsigned    scsiXfrCnt;
  624.     unsigned    value;
  625.     
  626.     IOLog("*** saveStatus 0x%x saveIntrStatus 0x%x\n", 
  627.         saveStatus, saveIntrStatus);
  628.     IOLog("*** scState = %s  scsiCmd = 0x%x\n", 
  629.         IOFindNameForValue(scState, scStateValues),
  630.         READ_REG(scsiCmd));
  631.         
  632.     cs = READ_REG(scsiStat);
  633.     cis = READ_REG(intrStatus);
  634.     IOLog("*** current status 0x%x current intrStatus 0x%x\n", cs, cis);
  635.     
  636.     IOLog("*** syncOffset %d  syncPeriod 0x%x\n", 
  637.         syncOffsetShadow, syncPeriodShadow);
  638.     
  639.     fifoDepth = READ_REG(currFifoState) & FS_FIFO_LEVEL_MASK;
  640.     scsiXfrCnt = READ_REG(currXfrCntLow);
  641.     value = READ_REG(currXfrCntMid);
  642.     scsiXfrCnt += (value << 8);
  643.     value = READ_REG(currXfrCntHi);
  644.     scsiXfrCnt += (value << 16);
  645.     IOLog("*** fifoDepth %d  scsiXfrCnt 0x%x\n", fifoDepth, scsiXfrCnt);
  646. #endif    DEBUG
  647. }
  648.  
  649.  
  650. @end    /* AMD_SCSI(Chip) */
  651.  
  652. /* end of AMD_Chip.m */
  653.  
  654.